package com.xlongwei.light4j.handler;

import java.io.File;
import java.util.Map;

import com.networknt.config.Config;
import com.networknt.utility.StringUtils;

import io.undertow.Handlers;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.PathHandler;
import io.undertow.server.handlers.ResponseCodeHandler;
import io.undertow.server.handlers.resource.ClassPathResourceManager;
import io.undertow.server.handlers.resource.FileResourceManager;
import io.undertow.server.handlers.resource.Resource;
import io.undertow.server.handlers.resource.ResourceHandler;
import io.undertow.server.handlers.resource.ResourceManager;
import lombok.extern.slf4j.Slf4j;

/**
 * <pre>
 * #handler.yml
 * handlers:
 *   - com.xlongwei.light4j.handler.StaticResourceHandler@static-resource
 * paths:
 *   - path: '/*'
 *   method: 'GET'
 *   exec:
 *     - static-resource
 * #static-resource.yml
 * path: /
 * baseFile: public
 * baseClasspath: public
 * directoryListingEnabled: false
 * welcomeFiles:
 * </pre>
 */
@Slf4j
public class StaticResourceHandler implements HttpHandler {
	private HttpHandler next;
	private String path = "/";
	private String baseFile = "public";
	private String baseClasspath = "public";
	private String[] welcomeFiles;
	private boolean directoryListingEnabled;

	public StaticResourceHandler() {
		this("static-resource");
	}

	public StaticResourceHandler(String configName) {
		loadConfig(configName);
		setNext();
	}

	@Override
	public void handleRequest(HttpServerExchange exchange) throws Exception {
		next.handleRequest(exchange);
	}

	private void loadConfig(String configName) {
		Map<String, Object> config = Config.getInstance().getJsonMapConfigNoCache(configName);
		log.info("{}", config);
		if (config == null) {
			return;
		}
		path = (String) config.get("path");
		baseFile = (String) config.get("baseFile");
		baseClasspath = (String) config.get("baseClasspath");
		welcomeFiles = StringUtils.split((String) config.get("welcomeFiles"), ',');
		directoryListingEnabled = (Boolean) config.get("directoryListingEnabled");
	}

	private void setNext() {
		HttpHandler handler = ResponseCodeHandler.HANDLE_404;
		if (StringUtils.isNotBlank(baseFile) && new File(baseFile).exists()) {
			if (StringUtils.isNotBlank(baseClasspath)) {
				File base = new File(baseFile);
				ResourceManager manager = null;

				if (directoryListingEnabled) {
					manager = new FileResourceManager(base);
					handler = setHandler(manager, handler);
				}

				manager = new ClassPathResourceManager(getClass().getClassLoader(), baseClasspath);
				handler = setHandler(manager, handler);

				manager = new FileResourceManager(new File(baseFile)) {
					@Override
					public Resource getResource(String p) {
						Resource r = super.getResource(p);// 访问GET /时转welcomeFiles，其次classpath，最后list目录
						return r == null || StringUtils.isBlank(r.getPath()) ? null : r;
					}
				};
				handler = setHandler(manager, handler);
			} else {
				ResourceManager manager = new FileResourceManager(new File(baseFile));
				handler = setHandler(manager, handler);
			}
		} else if (StringUtils.isNotBlank(baseClasspath)) {
			ResourceManager manager = new ClassPathResourceManager(getClass().getClassLoader(), baseClasspath);
			handler = setHandler(manager, handler);
		}
		PathHandler pathHandler = Handlers.path();
		pathHandler.addPrefixPath(path, handler);
		next = pathHandler;
	}

	private HttpHandler setHandler(ResourceManager manager, HttpHandler handler) {
		ResourceHandler resourceHandler = new ResourceHandler(manager, handler);
		resourceHandler.setDirectoryListingEnabled(directoryListingEnabled);
		if (welcomeFiles != null && welcomeFiles.length > 0) {
			resourceHandler.setWelcomeFiles(welcomeFiles);
		}
		return resourceHandler;
	}
}
